using System;
using System.Collections.Generic;
using System.Text;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Exceptions;

namespace Rensselaer_Event_Finder.Hibernate.DAO
{
     /// DAO - Data Access Object
     /// This is the generic class that will facilitate the 
     ///interaction between the application and the database 
     /// for specific entity types

    public abstract class GenericNHibernateDAO<T, ID>
    {
        /// <summary>
        /// The database session is needed for any communication with the database
        /// </summary>
        private ISession session;

        public ISession Session
        {
            get
            {
               if (session == null)
               {
                   try
                   {
                       session = NHibernateHelper.GetCurrentSession();
                   }
                   catch (Exception)
                   {
                       session = NHibernateHelper.getNewSession();
                   }
               }
                return session;
            }
            set
            {
                session = value;
            }
        }
        ///Find the entity by it's primary key 
        public T getById(ID id) 
        {
            try
            {
                return Session.Load<T>(id);
            }
            catch (ObjectNotFoundException he)
            {
                Console.Error.WriteLine(he);
            }
            return default(T);
        }

        /// <summary>
        ///  Get all the entities for a specific class
        /// </summary>
        /// <returns></returns>
        public IList<T> getAll()
        {
            return Session.CreateCriteria(typeof(T)).List<T>();
        }

        /// <summary>
        /// Make the entity persistent. It will be inserted or updated in the database
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public T save(T entity)
        {
            try
            {
                using (ITransaction transaction = Session.BeginTransaction())
                {
                    try
                    {
                        Session.SaveOrUpdate(entity);
                        Session.Flush();
                        transaction.Commit();
                    }
                    catch (Exception)
                    {

                    }
                }
            }
            catch (HibernateException he)
            {
                Console.Error.WriteLine(he);
            }
            return entity;
        }

        /// <summary>
        ///  Make the entity transient. It is deleted from the database
        /// </summary>
        /// <param name="entity"></param>
 
        public void delete(T entity)
        {
            try
            {
                using (ITransaction transaction = Session.BeginTransaction())
                {
                    Session.Delete(entity);
                    Session.Flush();
                    transaction.Commit();
                }
            }
            catch (HibernateException he)
            {
                Console.Error.WriteLine(he);
            }
        }

        public void executeSQL(String query)
        {
            Session.CreateSQLQuery(query).ExecuteUpdate();
        }
    }
}
